package com.lagou.lagouservicegateway.filter;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.RequestPath;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @Authther: mrwu
 * @date:2021/4/17-04
 * @Description:com.lagou.logougateway.filtrer
 */

/**
 * ip请求技术器防止一个客户端频繁请求某个接口
 */

@Component
public class IpcountFilter implements GlobalFilter, Ordered {

    private int countDruration;//计算周期单位为秒
    private int maxReq;//最大请求书
    private String urls;//匹配的接口路径用逗号隔开
    @Autowired
    RedisTemplate redisTemplate;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ValueOperations opsForValue = redisTemplate.opsForValue();//redis 字符串操作句柄
        //获取请求的URL
        RequestPath path = exchange.getRequest().getPath();
        //获取请求的客户端地址
        InetSocketAddress remoteAddress = exchange.getRequest().getRemoteAddress();
       //这里先考虑只对单个路径进行匹配
        System.out.println(path);
        //如果不是过滤路径直接进入下一过滤器链
        if (!path.toString().startsWith("/user/register")){
            return chain.filter(exchange);
        }
        String keyprifix = remoteAddress+":"+"/user/register"+":";//redis存储前缀
        //从redis中取出key的数量，如果数量大于maxreq 直接返回请求次数过多
        Set keys = redisTemplate.keys(keyprifix+"*");
        if (keys.size()>10){//如果有效key大于请求数，则返回
            ServerHttpResponse response = exchange.getResponse();
            DataBuffer wrap = response.bufferFactory().wrap("request too many".getBytes(StandardCharsets.UTF_8));
            response.setStatusCode(HttpStatus.UNAUTHORIZED);//返回不给权限
            return   response.writeWith(Mono.just(wrap));
        }
       //前缀+uuid 作为key存入redis 过期时间为计算周期 防止覆盖 默认60秒
        opsForValue.set(keyprifix+UUID.randomUUID(), "",60, TimeUnit.SECONDS);

        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return 0;
    }
}
